define [
	'jquery'
	'sammy/sammy-0.7.1.min.js'
], ($) ->

	# Define a publish-subscribe mechanism based on jQuery events. We use a
	# closure to make the ps object private.
	( ->
		ps = $({})
		$.subscribe = ->
			ps.on.apply ps, arguments
			return
		$.unsubscribe = ->
			ps.off.apply ps, arguments
			return
		$.publish = ->
			ps.trigger.apply ps, arguments
			return
	)()

	# Define a jQuery method to label a custom plugin with a given
	# classname or to check if an object is a custom plugin.
	$.fn.mb_plugin = (x) ->
		if x then @addClass "mb_plugin #{x}" else @hasClass "mb_plugin"


	# Define a jQuery method to get a template from a DOM element and
	# return it as a text string.
	$.fn.template = ->
		tpl = @html()
		# Remove spaces between tags
		tpl = tpl?.replace(/>\s+</g, '><')
		# Remove leading and tra'.iling spaces
		tpl = tpl?.replace(/^\s+/g, '')?.replace(/\s+$/g, '')
		# Decode HTML entities in <%= and %> tags used by template
		tpl = tpl?.replace(/&lt;%=/g, '<%=')?.replace(/%&gt;/g, '%>')
		return tpl


	# Define a Sammy app helper to build content from a data object using a
	# template located in a jQuery object. It uses the Sammy.Template
	# plugin which supplies a Sammy event method called 'template()'.
	#
	# If data underspecifies the properties defined in template then
	# template() generates an Uncaught ReferenceError, but things are ok if
	# data overspecifies.

	# If 2nd param data is not given to template(), it does not return a
	# function as expected, because data is extended by the Sammy context.
	# However, if data is not extended then basic rendering does now work,
	# because some needed functions would be missing. Therefore, we cannot
	# code as follows.
	#tpl = S.template tpl
	#content = tpl data

	content = ($tpl, data) ->
		try
			@template $tpl.template(), data
		catch e
			if e instanceof ReferenceError
				#console.log "#{e.name}: #{JSON.stringify e.arguments} #{e.type}"
				data[e.arguments] = "" for i of e.arguments
				@content($tpl, data)
			else
				throw e
			return @template $tpl.template(), data

	# Ignore
	$.expr[":"].exactly = (obj, index, meta, stack) -> ($(obj).text() is meta[3])

	# Ignore
	request = (options, callback) ->
		options.success = (obj) -> callback null, obj
		options.error = (err) -> callback if err then err else true
		options.data = JSON.stringify options.data if options.data and typeof options.data is 'object'
		unless options.dataType
			options.processData = false
			options.contentType = 'application/json'
			options.dataType = 'json'
		$.ajax options

	# Ignore
	param = (a) ->
		# Query param builder from jQuery, had to copy out to remove conversion of spaces to +
		# This is important when converting datastructures to querystrings to send to CouchDB.

		s = []

		buildParams = (prefix, obj) ->
			if jQuery.isArray obj
				jQuery.each obj, (i, v) ->
					if /\[\]$/.test prefix
						add prefix, v
					else
						buildParams prefix + "[" + (if typeof v is "object" or jQuery.isArray(v) then i else "") +"]", v
			else if obj isnt null and typeof obj is "object"
				jQuery.each obj, (k, v) -> buildParams "#{prefix}[#{k}]", v
			else
				add prefix, obj
				
		add = (key, value) ->
			value = if jQuery.isFunction(value) then value() else value
			s[ s.length ] = "#{encodeURIComponent key}=#{encodeURIComponent value}"
		
		if jQuery.isArray(a) or a.jquery
			jQuery.each a, -> add @name, @value
		else
			buildParams prefix, a[prefix] for prefix in a
		s.join "&"
	

		
	doc = () ->
		@__proto__.parse = (_array) -> @add _array[_i]['name'], _array[_i]['value'] for _i of _array 
		@__proto__.add = (node, value, overwrite) ->
			overwrite or= off
			try
				eval "_temp = this." + node
				if not _temp? or overwrite then _array = value
				else
					_array = []
					if _temp instanceof Array then _array.push _temp[_i] for _i of _temp else _array.push _temp
					_array.push value
				eval "this." + node + " = _array"
			catch err
				_errNode = err.message.match(/'(.*?)'/)[1]
				_array = node.split(".")
				_badIndex = _array.indexOf(_errNode)
		
				unless node.indexOf(_errNode) is node.lastIndexOf(_errNode)
					for _i in _array
						_node = _array.slice(0, Number(_i) + 1).join(".")
						if eval("this." + _node)?
							_badIndex = Number(_i) + 1
							break
				
				_existing = _array.slice(0, _badIndex).join(".")
				_field = _array.slice(_badIndex - 1).reverse()[0]
				_array = _array.slice(_badIndex - 1).reverse().slice(1)
				
				for _i of _array
					eval "_$" + _array[_i] + " = {};"
					eval "_$" + _array[_i] + "." + _field + " = '" + value + "'"  if Number(_i) is 0
					eval "_$" + _array[_i] + "." + _array[_i - 1] + " = " + "_$" + _array[_i - 1] + ""  if Number(_i) > 0
					_temp = eval "_$" + _array[_i]

				eval "this." + _existing + " = _$" + _array[_array.length - 1]
				
		return
		
	objFormat = (obj) ->
		for i of obj
			if typeof obj[i] is "string"
				if i.toString() is "_id" or i.toString() is "_rev"
					continue
				if i.toString() is 'postal_code'
					obj[i] = obj[i].toUpperCase()
					continue
				else
					obj[i] = obj[i].toCaps()
		return obj
			
	# Helper function to identify if a string _str has a pattern resembling a Postal Code
	# If true, then return replaced postal code format without spaces and dashes
	# If false, return original string (not a postal code)
	String.prototype.isPostal = (b) ->
		PCRegEx = /[A-Z][0-9][A-Z] [0-9][A-Z][0-9]/
		if b? and b is 0
			if @replace(PCRegEx, "").length isnt 0
				return false
			else
				return PCRegEx.test(@)
		else
			_str = @replace(/[ -]/, '')
			if /[a-z][0-0][a-z][0-9][a-z][0-9]/.test(_str)
				return _str
			else 
				return @

	# Helper function to identify if a string _str has a pattern resembling to a phone number
	# If true, then return replaced phone format without spaces, parentheses, periods, or dashes
	# If false, then return the original string (not a phone number)
	String.prototype.isPhone = (b) ->
		phone = @replace(/[\. \-\(\)]/g, '')
		PhoneRegEx = /\([0-9]{3}\) [0-9]{3}\-[0-9]{4}/
		if b? and b is 0
			if @replace(PhoneRegEx, "").length isnt 0
				return false
			else
				return PhoneRegEx.test(@)
		if b? and b is 1
			return ["(", phone.substr(0,3), ") ", phone.substr(3, 3), "-", phone.substr(6, 4)].join("")
		if isNaN(phone) then return @ else return phone

	String.prototype.toCaps = () ->
		_ucwordlist = ['bc', 'nwt', 'ab', 'sk', 'on', "p.o.", "id"]
		_lcwordlist = ['and', 'or']
		for i of _words = @split(' ')
			_words[i] = _words[i].charAt(0).toUpperCase() + _words[i].slice(1).toLowerCase() 
			if _words[i].toLowerCase().matches(_ucwordlist)
				_words[i] = _words[i].toUpperCase()
				continue
			if _words[i].toLowerCase().matches(_lcwordlist)
				_words[i] = _words[i].toLowerCase()
				continue
			if (t = _words[i].split(".")).length isnt 0
				for j of t
					t[j] = t[j].charAt(0).toUpperCase() + t[j].slice(1).toLowerCase()
				_words[i] = t.join(".")
		return _words.join(' ')

	# Helper function to sort in alphabetical or numerical order
	sortby = (field, reverse) -> 
		reverse or= false
		(a, b) -> 
			if isNaN(a[field])
				A = a[field].replace(/[,#-]/g, '').toLowerCase()
				B = b[field].replace(/[,#-]/g, '').toLowerCase()
				if reverse then i = 1 else i = -1
				if A < B then return i
				if A > B then return -i
				else return 0
			else
				return a[field] - b[field]

	String.prototype.matches = (_array) ->
		if _array.indexOf(this.toLowerCase()) isnt -1 then return true else return false

	return {
		content: content,
		doc: doc, 
		sortby: sortby, 
		objFormat: objFormat
	}
